#include "bsp_lcd.h"
//#include "bsp_font.h"
extern const unsigned char ASCII[];

extern  const uint8_t Font5x7[];

void LCD_SPI_SendData(unsigned char data)
{
	unsigned int i =0;
	LCD_CS_OFF;//����CSƬѡ�ź� 
	for(i=0; i<8; i++ ) //��ʱ�����ϲ����˸�ʱ�ӣ�ͬʱ��8����һ�ηŵ���������
	{
		LCD_SCK_OFF;//ʱ��������		
		if(data & 0x80) LCD_MOSI_ON;
		else            LCD_MOSI_OFF;		
		LCD_SCK_ON;//ʱ��������		
		data <<=1;
	}
	LCD_CS_ON;//����CS
}

void LCD_Write_Command(unsigned char i)//д����ʱ�轫 PB14 ��Ϊ�͵�ƽ
{
	LCD_RS_OFF;
	LCD_SPI_SendData(i);
}

void LCD_Write_Data(unsigned char i)//д����ʱ�轫 PB14 ��Ϊ�ߵ�ƽ
{
	LCD_RS_ON;
	LCD_SPI_SendData(i);
}

//����Ļ�ϻ�һ����
void Draw_Point(unsigned char x, unsigned char y, unsigned int color)
{
	y += 32;
	
	LCD_Write_Command(0x2A);             
	LCD_Write_Data(0x00);             
	LCD_Write_Data(x);             

	LCD_Write_Command(0x2B);             
	LCD_Write_Data(0x00);             
	LCD_Write_Data(y);             
  	
	LCD_Write_Command(0x2c); 
	LCD_Write_Data(color>>8);             
	LCD_Write_Data(color);  	
}

void Display_Font(unsigned char Xstart,unsigned char Ystart,unsigned int Font_Color,unsigned int Background_Color,const unsigned char *Image,unsigned char num)
{
	unsigned char i,j,k,Send_Buf;

    for(i=0;i<32;i++)//��ӡһ��32*32�ĺ���
	{
		for(j=0;j<4;j++) 
		{
			Send_Buf=*(Image+i*4+j+num*32*4);
			for (k=0;k<8;k++)	
			{	
		    	if(Send_Buf&(0x80>>k))	
					Draw_Point(Xstart+j*8+k,Ystart+i,Font_Color);//��ӡ������ɫ
				else 
					Draw_Point(Xstart+j*8+k,Ystart+i,Background_Color);//��ӡ������ɫ
			}
		}
	}
}

//ȫ����ʾһ��ͼƬ�� p ΪҪ��ʾ����ɫֵ��ָ��,8λ��ʽ
void Display_Picture(const unsigned char *p)
{
	unsigned char i,j; 

	LCD_SetRegion(0,Row-1,0,Column-1);	//������ʾ����
	for(i=0;i<Row;i++)//��
	{
	    for(j=0;j<Column;j++)//��
		{    
			LCD_Write_Data(*(p+1));				  
			LCD_Write_Data(*p);
			p += 2;
		}
	}
}

void Display_String(unsigned char Xstart, unsigned char Ystart, unsigned int Font_Color,unsigned int Background_Color, unsigned char *string)
{
	unsigned char i,j,k;

	while(*string) 
	{	
		k=(*string)-32;
		for(i=0;i<16;i++)
		{
			for(j=0;j<8;j++) 
			{
				if(ASCII[k*16+i]&(0x80>>j))	
					Draw_Point(Xstart+j,Ystart+i,Font_Color);//��ӡ������ɫ
				else 
					Draw_Point(Xstart+j,Ystart+i,Background_Color);//��ӡ������ɫ
			}
		}
		Xstart+=8;
		string++;
	}
}

//��Ҫ��ʾ��������н綨��дͼƬ�ʹ���ɫ����ʱҪ����
void LCD_SetRegion(unsigned char Xstart,unsigned char Xend,unsigned char Ystart,unsigned char Yend)
{
	Ystart += 32;
	Yend += 32;
	
	LCD_Write_Command(0x2A);             
	LCD_Write_Data(Xstart>>8);             
	LCD_Write_Data(Xstart);             
	LCD_Write_Data(Xend>>8);             
	LCD_Write_Data(Xend);             
	
	LCD_Write_Command(0x2B);             
	LCD_Write_Data(Ystart>>8);             
	LCD_Write_Data(Ystart);             
	LCD_Write_Data(Yend>>8);             
	LCD_Write_Data(Yend);   	

	LCD_Write_Command(0x2c);
}

void Full_Display_Color(unsigned int color)//ȫ����ʾ����ɫ��colorΪ16λ����ɫ���ݣ���������λ����5R 6G 5B 
{
	unsigned int i,j;
	LCD_SetRegion(0,Row-1,0,Column-1);//������ʾ����

	for(i=0;i<Row;i++)
	{
	    for(j=0;j<Column;j++)
		{    
			LCD_Write_Data(color>>8);
			LCD_Write_Data(color);
		}
	}
}

void  LCD_Init(void)//��Ҫ��������ɴ���ģʽ�����ü����͸�λ�ź���ģ������ڲ���ʼ��
{ 	
	LCD_RST_OFF;//��λ��ʾ�����ڶ���ʾ��д��ʼ������֮ǰ�������LCD���д˲���
	HAL_Delay(100);
	LCD_RST_ON;
	HAL_Delay(50);


	LCD_Write_Command(0x11); //Exit Sleep
	HAL_Delay(50);

	LCD_Write_Command(0xB1);//Set Frame Rate
	LCD_Write_Data(0x02);
	LCD_Write_Data(0x35);
	LCD_Write_Data(0x36);

	LCD_Write_Command(0xB2);//Set Frame Rate
	LCD_Write_Data(0x02);
	LCD_Write_Data(0x35);
	LCD_Write_Data(0x36);

	LCD_Write_Command(0xB3);//Set Frame Rate
	LCD_Write_Data(0x02);
	LCD_Write_Data(0x35);
	LCD_Write_Data(0x36);
	LCD_Write_Data(0x02);
	LCD_Write_Data(0x35);
	LCD_Write_Data(0x36);
	LCD_Write_Data(0x02);
	LCD_Write_Data(0x35);
	LCD_Write_Data(0x36);

	LCD_Write_Command(0xB4);//Set Frame Rate
	LCD_Write_Data(0x03);

	LCD_Write_Command(0xC0);
	LCD_Write_Data(0xA2);
	LCD_Write_Data(0x02);
	LCD_Write_Data(0x84);
	LCD_Write_Command(0xC1);
	LCD_Write_Data(0xC5);
	LCD_Write_Command(0xC2);
	LCD_Write_Data(0x0D);
	LCD_Write_Data(0x00);
	LCD_Write_Command(0xC3);
	LCD_Write_Data(0x8D);
	LCD_Write_Data(0x2A);
	LCD_Write_Command(0xC4);
	LCD_Write_Data(0x8D);
	LCD_Write_Data(0xEE);
	//---------------------------------End ST7735S Power Sequence-------------------------------------//
	LCD_Write_Command(0xC5); //VCOM
	LCD_Write_Data(0x03);
	LCD_Write_Command(0x36); //MX, MY, RGB mode
	LCD_Write_Data(0xC8);
	//------------------------------------ST7735S Gamma Sequence-----------------------------------------//
	LCD_Write_Command(0XE0);
	LCD_Write_Data(0x12);
	LCD_Write_Data(0x1C);
	LCD_Write_Data(0x10);
	LCD_Write_Data(0x18);
	LCD_Write_Data(0x33);
	LCD_Write_Data(0x2C);
	LCD_Write_Data(0x25);
	LCD_Write_Data(0x28);
	LCD_Write_Data(0x28);
	LCD_Write_Data(0x27);
	LCD_Write_Data(0x2F);
	LCD_Write_Data(0x3C);
	LCD_Write_Data(0x00);
	LCD_Write_Data(0x03);
	LCD_Write_Data(0x03);
	LCD_Write_Data(0x10);
	LCD_Write_Command(0XE1);
	LCD_Write_Data(0x12);
	LCD_Write_Data(0x1C);
	LCD_Write_Data(0x10);
	LCD_Write_Data(0x18);
	LCD_Write_Data(0x2D);
	LCD_Write_Data(0x28);
	LCD_Write_Data(0x23);
	LCD_Write_Data(0x28);
	LCD_Write_Data(0x28);
	LCD_Write_Data(0x26);
	LCD_Write_Data(0x2F);
	LCD_Write_Data(0x3B);
	LCD_Write_Data(0x00);
	LCD_Write_Data(0x03);
	LCD_Write_Data(0x03);
	LCD_Write_Data(0x10);
	//------------------------------------End ST7735S Gamma Sequence-----------------------------------------//
	LCD_Write_Command(0x3A); //65k mode
	LCD_Write_Data(0x05);
	LCD_Write_Command(0x29); //Display on
}

// 发送命令或数据到 ST7735
void ST7735_Write(uint8_t value, uint8_t cmd)
{
    if (cmd == ST7735_CMD)
        HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_RESET);
    else
        HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET);

    HAL_SPI_Transmit(&hspi1, &value, 1, HAL_MAX_DELAY);
}

// 设置命令或数据模式
void ST7735_Select()
{
    HAL_GPIO_WritePin(GPIO_CS_CONTROL, GPIO_CS_PIN, GPIO_PIN_RESET);
}

void ST7735_Unselect()
{
    HAL_GPIO_WritePin(GPIO_CS_CONTROL, GPIO_CS_PIN, GPIO_PIN_SET);
}

void ST7735_Reset()
{
    HAL_GPIO_WritePin(GPIO_RESET_CONTROL, GPIO_RESET_PIN, GPIO_PIN_RESET);
    HAL_Delay(5);
    HAL_GPIO_WritePin(GPIO_RESET_CONTROL, GPIO_RESET_PIN, GPIO_PIN_SET);
}

void ST7735_WriteCommand(uint8_t cmd)
{
    HAL_GPIO_WritePin(GPIO_CMD_CONTROL, GPIO_CMD_PIN, GPIO_PIN_RESET);
    HAL_SPI_Transmit(&hspi1, &cmd, sizeof(cmd), HAL_MAX_DELAY);
}

void ST7735_WriteData(uint8_t* buff, size_t buff_size)
{
    HAL_GPIO_WritePin(GPIO_CMD_CONTROL, GPIO_CMD_PIN, GPIO_PIN_SET);
    HAL_SPI_Transmit(&hspi1, buff, buff_size, HAL_MAX_DELAY);
}

void ST7735_WriteDataByte(uint8_t data)
{
    HAL_GPIO_WritePin(GPIO_CMD_CONTROL, GPIO_CMD_PIN, GPIO_PIN_SET);
    HAL_SPI_Transmit(&hspi1, &data, sizeof(data), HAL_MAX_DELAY);
}

// 背光控制
void ST7735_BacklightOn()
{
    HAL_GPIO_WritePin(GPIO_BLACK_CONTROL, GPIO_BLACK_PIN, GPIO_PIN_SET);
}

void ST7735_BacklightOff()
{
    HAL_GPIO_WritePin(GPIO_BLACK_CONTROL, GPIO_BLACK_PIN, GPIO_PIN_RESET);
}

// 设置屏幕窗口
void ST7735_SetAddressWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)
{
    ST7735_WriteCommand(0x2A); // 列地址设置
    uint8_t data[] = {0x00, x0, 0x00, x1};
    ST7735_WriteData(data, sizeof(data));

    ST7735_WriteCommand(0x2B); // 行地址设置
    uint8_t data2[] = {0x00, y0, 0x00, y1};
    ST7735_WriteData(data2, sizeof(data2));

    ST7735_WriteCommand(0x2C); // 发送数据
}

// 填充屏幕
void ST7735_FillScreen(uint16_t color)
{
    ST7735_SetAddressWindow(0, 0, ST7735_WIDTH-1, ST7735_HEIGHT-1);
    uint8_t data[] = { color >> 8, color & 0xFF };

    for (uint16_t i = 0; i < ST7735_WIDTH * ST7735_HEIGHT; i++)
    {
        ST7735_WriteData(data, 2);
    }
}

// 初始化 ST7735
void ST7735_Init()
{
    ST7735_Select();
    // ST7735_Reset();

    // 初始化命令序列
    ST7735_WriteCommand(0x01); // 软件复位
    HAL_Delay(150);

    ST7735_WriteCommand(0x11); // 退出睡眠模式
    HAL_Delay(500);

    // 配置帧率控制
    ST7735_WriteCommand(0xB1);
    uint8_t frame_rate[] = {0x01, 0x2C, 0x2D};
    ST7735_WriteData(frame_rate, sizeof(frame_rate));

    // 其他配置命令
    ST7735_WriteCommand(0x36);
    uint8_t mem_access[] = {0xC8};
    ST7735_WriteData(mem_access, sizeof(mem_access));

    ST7735_WriteCommand(0x3A);
    uint8_t pixel_format[] = {0x05}; // 16-bit color
    ST7735_WriteData(pixel_format, sizeof(pixel_format));

    ST7735_WriteCommand(0x29); // 显示开启

//    ST7735_Unselect();
}

void ST7735_DrawChar(int16_t x, int16_t y, char ch, uint16_t color, uint16_t bg, uint8_t size)
{
    if ((x >= ST7735_WIDTH) || (y >= ST7735_HEIGHT) || ((x + 5 * size - 1) < 0) || ((y + 7 * size - 1) < 0))
        return;

    for (int8_t i = 0; i < 5; i++ ) {
        uint8_t line = Font5x7[(ch - 0x20) * 5 + i];
        for (int8_t j = 0; j < 8; j++) {
            if (line & 0x1) {
                if (size == 1) // 默认大小
                    ST7735_DrawPixel(x + i, y + j, color);
                else {  // 大字体
                    ST7735_FillRect(x + (i * size), y + (j * size), size, size, color);
                }
            } else if (bg != color) {
                if (size == 1) // 默认大小
                    ST7735_DrawPixel(x + i, y + j, bg);
                else {  // 大字体
                    ST7735_FillRect(x + i * size, y + j * size, size, size, bg);
                }
            }
            line >>= 1;
        }
    }
}

void ST7735_DrawString(int16_t x, int16_t y, const char* str, uint16_t color, uint16_t bg, uint8_t size)
{
    while (*str) {
        if (*str == '\n') {
            y += size * 8;
            x = 0;
        } else if (*str == '\r') {
            // 忽略
        } else {
            ST7735_DrawChar(x, y, *str, color, bg, size);
            x += size * 6;
        }
        str++;
    }
}

void ST7735_DrawPixel(int16_t x, int16_t y, uint16_t color)
{
    if((x < 0) || (x >= ST7735_WIDTH) || (y < 0) || (y >= ST7735_HEIGHT)) return;

    ST7735_SetAddressWindow(x, y, x+1, y+1);

    uint8_t data[] = { color >> 8, color & 0xFF };
    ST7735_WriteData(data, sizeof(data));
}

void ST7735_FillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
{
    if((x >= ST7735_WIDTH) || (y >= ST7735_HEIGHT)) return;
    if((x + w - 1) >= ST7735_WIDTH)  w = ST7735_WIDTH  - x;
    if((y + h - 1) >= ST7735_HEIGHT) h = ST7735_HEIGHT - y;

    ST7735_SetAddressWindow(x, y, x + w - 1, y + h - 1);

    uint8_t data[] = { color >> 8, color & 0xFF };
    for(y = h; y > 0; y--) {
        for(x = w; x > 0; x--) {
            ST7735_WriteData(data, sizeof(data));
        }
    }
}











